package com.start.form.engine.store.mysql;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.start.common.dataRule.StartQueryWrapper;
import com.start.common.details.BaseUserDetails;
import com.start.common.exceptions.StartBusException;
import com.start.common.tools.UUIdTools;
import com.start.form.engine.core.StartColumnInfo;
import com.start.form.engine.core.StartFormEngineConstant.FormBaseColumns;
import com.start.form.engine.core.entity.StartFormConfig;
import com.start.form.engine.core.model.StartFormColumnModel;
import com.start.form.engine.core.model.StartFormData;
import com.start.form.engine.core.storage.StartBaseFormStorageEngineService;
import com.start.form.engine.core.vo.StartFormColumnVo;
import com.start.form.engine.store.mysql.mapper.SqlTableDataStorageMapper;
import com.start.security.StartTokenTools;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据库存储器
 */
@Component(SqlTableDataStorage.STORAGE_KEY)
public class SqlTableDataStorage extends StartBaseFormStorageEngineService {

    public static final String STORAGE_KEY = "mySqlStorageEngine";


    /**
     * 获取当前存储器唯一标识 一般默认当前bean 名称
     *
     * @return
     */
    @Override
    public String getStorageKey() {
        return STORAGE_KEY;
    }

    /**
     * 获取当前存储器名称
     *
     * @return
     */
    @Override
    public String getStorageLabel() {
        return "mysql数据库存储器";
    }

    @Autowired
    private SqlTableDataStorageMapper storageMapper;


    @Override
    public Page storagePage(StartFormConfig config, Page page, List<StartFormColumnModel> column, StartQueryWrapper query) {
        Page storage = storageMapper.pageStorage(page, config.getTableName(), column, query);
        List records = storage.getRecords();
        storage.setRecords(null);
        List<JSONObject> list = listMapToJSON(records);
        storage.setRecords(list);
        return storage;
    }

    private List<JSONObject> listMapToJSON(List rows) {
        List<JSONObject> list = new ArrayList<>(rows.size());
        if (rows.isEmpty()) return list;
        for (Object row : rows) {
            list.add(JSONObject.from(row));
        }
        return list;
    }

    @Override
    public List<JSONObject> storageList(StartFormConfig config, List<StartFormColumnModel> column, StartQueryWrapper query) {
        String tableName = config.getTableName();
        List<Map<String, Object>> maps = storageMapper.storageList(tableName, column, query);
        return listMapToJSON(maps);
    }


    @Override
    public List<StartFormColumnModel> getColumnConfig(StartFormConfig formConfig) {
        return storageMapper.getTableColumns(formConfig.getTableName());
    }

    @Override
    public String storageSave(StartFormConfig config, List<StartFormColumnModel> columns, JSONObject data) {
        List<StartFormColumnModel> tableColumns = storageMapper.getTableColumns(config.getTableName());
        String id = UUIdTools.createId32();
        if (data.containsKey(FormBaseColumns.COLUMN_PK_NAME)) {
            data.replace(FormBaseColumns.COLUMN_PK_NAME, id);
        } else {
            data.put(FormBaseColumns.COLUMN_PK_NAME, id);
        }
        List<StartFormData> formDatas = new ArrayList<>();
        for (StartFormColumnModel column : tableColumns) {
            if (!data.containsKey(column.getProp())) continue;
            StartFormData formData = new StartFormData();
            formData.setDataValue(data.getString(column.getProp()));
            formData.setProp(column.getProp());
            formDatas.add(formData);
        }
        storageMapper.storageSave(config.getTableName(), formDatas);
        return id;
    }

    /**
     * 获取当前用户信息
     *
     * @return 当前用户信息
     */
    private BaseUserDetails getCurrentUser() {
        try {
            return StartTokenTools.getCurrentUser();
        } catch (Exception e) {
            return null;
        }

    }

    @Override
    public long storageUpdate(StartFormConfig config, List<StartFormColumnModel> columns, JSONObject data, StartQueryWrapper queryWrapper) {
        List<StartFormColumnModel> tableColumns = storageMapper.getTableColumns(config.getTableName());
        if (!data.containsKey(FormBaseColumns.COLUMN_UPDATE_TIME)) {
            data.put(FormBaseColumns.COLUMN_UPDATE_TIME, LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
        }
        if (!data.containsKey(FormBaseColumns.COLUMN_UPDATE_BY) && getCurrentUser() != null) {
            BaseUserDetails userDetails = getCurrentUser();
            data.put(FormBaseColumns.COLUMN_UPDATE_BY, userDetails.getUserId());
        }
        List<StartFormData> formDatas = new ArrayList<>();
        for (StartFormColumnModel column : tableColumns) {
            if (!data.containsKey(column.getProp())) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_PK_NAME)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_CREATE_TIME)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_CREATE_BY)) continue;
            StartFormData formData = new StartFormData();
            formData.setDataValue(data.getString(column.getProp()));
            formData.setProp(column.getProp());
            formDatas.add(formData);
        }
        return storageMapper.storageUpdate(config.getTableName(), formDatas, queryWrapper);
    }

    /**
     * 删除数据
     *
     * @param config       数据表配置
     * @param queryWrapper 条件
     * @return long 影响行数量
     */
    @Override
    protected long storageRemove(StartFormConfig config, StartQueryWrapper queryWrapper) {
        if (StringUtils.isEmpty(queryWrapper.getCustomSqlSegment())) {
            throw new StartBusException("系统禁止删除全部数据");
        }
        Long num = storageMapper.storageRemove(config.getTableName(), queryWrapper);
        if (num == null) {
            return 0;
        }
        return num;
    }

    /**
     * 查询数据数量
     *
     * @param config       数据表配置
     * @param queryWrapper 查询条件
     * @return long 数据总数
     */
    @Override
    protected long storageCount(StartFormConfig config, StartQueryWrapper queryWrapper) {
        return storageMapper.storageCount(config.getTableName(), queryWrapper);
    }


    @Override
    public List<StartFormColumnModel> storageSynchronizationTable(StartFormConfig formConfig, StartColumnInfo startColumnInfo) {
        Map<String, String> table = storageMapper.getTableByTableName(formConfig.getTableName());
        if (table == null || table.isEmpty()) {
            return createSQLTable(formConfig, startColumnInfo);
        }
        return updateTable(table, formConfig, startColumnInfo);
    }

    /**
     * 修改数据表
     *
     * @param oldTableInfo    旧表信息
     * @param formConfig      新表信息
     * @param startColumnInfo 列信息
     * @return List<StartFormColumnModel> 列信息
     */
    private List<StartFormColumnModel> updateTable(Map<String, String> oldTableInfo, StartFormConfig formConfig, StartColumnInfo startColumnInfo) {
        if (!oldTableInfo.containsKey("table_comment") || oldTableInfo.getOrDefault("table_comment", "").equals(formConfig.getName())) {
            storageMapper.updateTableComment(formConfig);
        }
        List<StartFormColumnModel> columns = new ArrayList<>();
        columns.addAll(startColumnInfo.getAddLists());
        columns.addAll(startColumnInfo.getEditColumns());
        columns.forEach(e -> e.setId(e.getProp()));
        deleteColumns(formConfig.getTableName(), startColumnInfo.getDeleteColumns());
        updateColumns(formConfig.getTableName(), startColumnInfo.getEditColumns());
        addColumns(formConfig.getTableName(), startColumnInfo.getAddLists());
        return columns;
    }

    /**
     * 创建数据表
     *
     * @param formConfig      表单配置信息
     * @param startColumnInfo 列信息
     * @return List
     */
    private List<StartFormColumnModel> createSQLTable(StartFormConfig formConfig, StartColumnInfo startColumnInfo) {
        List<StartFormColumnModel> columns = new ArrayList<>();
        columns.addAll(startColumnInfo.getAddLists());
        columns.addAll(startColumnInfo.getEditColumns());
        columns.forEach(e -> e.setId(e.getProp()));
        storageMapper.createTable(formConfig, columns);
        return columns;
    }

    /**
     * 删除列
     *
     * @param tableName
     * @param deleteLists
     */
    private void deleteColumns(String tableName, List<StartFormColumnModel> deleteLists) {
        if (deleteLists == null || deleteLists.size() < 1) return;
        for (StartFormColumnModel column : deleteLists) {
            if (column.getProp().equals(FormBaseColumns.COLUMN_CREATE_BY)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_CREATE_TIME)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_UPDATE_BY)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_UPDATE_TIME)) continue;
            if (column.getProp().equals(FormBaseColumns.COLUMN_PK_NAME)) continue;
            storageMapper.deleteColumn(tableName, column);
        }
    }

    private void updateColumns(String tableName, List<StartFormColumnVo> editLists) {
        if (editLists == null || editLists.isEmpty()) return;
        for (StartFormColumnVo column : editLists) {
            storageMapper.updateColumn(tableName, column);
        }
    }

    private void addColumns(String tableName, List<StartFormColumnModel> addLists) {
        if (addLists == null || addLists.isEmpty()) return;
        for (StartFormColumnModel column : addLists) {
            storageMapper.addColumn(tableName, column);

        }
    }


    @Override
    public void storageDeleteTable(StartFormConfig formConfig) {
        Map<String, String> table = storageMapper.getTableByTableName(formConfig.getTableName());
        if (table != null && !table.isEmpty())
            storageMapper.deleteTable(formConfig.getTableName());

    }


    @Override
    public void clearData(StartFormConfig formConfig) {
        storageMapper.clearData(formConfig.getTableName());
    }
}
